// Copyright Epic Games, Inc. All Rights Reserved.


#include "LyraContextEffectComponent.h"

#include "Engine/World.h"
#include "LyraContextEffectsSubsystem.h"
#include "PhysicalMaterials/PhysicalMaterial.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraContextEffectComponent)

class UAnimSequenceBase;
class USceneComponent;



// 设置此组件属性的默认值
ULyraContextEffectComponent::ULyraContextEffectComponent()
{
	// 禁用组件tick，启用自动激活
	PrimaryComponentTick.bCanEverTick = false; // 设置永不tick
	bAutoActivate = true; // 自动激活
	// ...
}


// 游戏开始时调用
void ULyraContextEffectComponent::BeginPlay()
{
	Super::BeginPlay(); // 调用父类BeginPlay

	// ...
	CurrentContexts.AppendTags(DefaultEffectContexts); // 追加默认效果上下文
	CurrentContextEffectsLibraries = DefaultContextEffectsLibraries; // 设置当前上下文效果库

	// 在游戏开始时，加载并添加上下文效果配对
	if (const UWorld* World = GetWorld()) // 获取世界
	{
		if (ULyraContextEffectsSubsystem* LyraContextEffectsSubsystem = World->GetSubsystem<ULyraContextEffectsSubsystem>()) // 获取上下文效果子系统
		{
			LyraContextEffectsSubsystem->LoadAndAddContextEffectsLibraries(GetOwner(), CurrentContextEffectsLibraries); // 加载并添加上下文效果库
		}
	}
}

void ULyraContextEffectComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	// 在游戏结束时，移除不必要的上下文效果配对
	if (const UWorld* World = GetWorld()) // 获取世界
	{
		if (ULyraContextEffectsSubsystem* LyraContextEffectsSubsystem = World->GetSubsystem<ULyraContextEffectsSubsystem>()) // 获取上下文效果子系统
		{
			LyraContextEffectsSubsystem->UnloadAndRemoveContextEffectsLibraries(GetOwner()); // 卸载并移除上下文效果库
		}
	}

	Super::EndPlay(EndPlayReason); // 调用父类EndPlay
}

/**
 * 接口的AnimMotionEffect函数实现
 */
void ULyraContextEffectComponent::AnimMotionEffect_Implementation(const FName Bone, const FGameplayTag MotionEffect, USceneComponent* StaticMeshComponent,
	const FVector LocationOffset, const FRotator RotationOffset, const UAnimSequenceBase* AnimationSequence,
	const bool bHitSuccess, const FHitResult HitResult, FGameplayTagContainer Contexts,
	FVector VFXScale, float AudioVolume, float AudioPitch)
{
	// 准备组件
	TArray<UAudioComponent*> AudioComponentsToAdd; // 要添加的音频组件
	TArray<UNiagaraComponent*> NiagaraComponentsToAdd; // 要添加的Niagara组件

	FGameplayTagContainer TotalContexts; // 总上下文

	// 聚合上下文
	TotalContexts.AppendTags(Contexts); // 追加传入上下文
	TotalContexts.AppendTags(CurrentContexts); // 追加当前上下文

	// 检查是否将物理表面类型转换为上下文
	if (bConvertPhysicalSurfaceToContext) // 如果启用转换
	{
		// 获取物理材质类型指针
		TWeakObjectPtr<UPhysicalMaterial> PhysicalSurfaceTypePtr = HitResult.PhysMaterial; // 物理表面类型指针

		// 检查指针是否正常
		if (PhysicalSurfaceTypePtr.IsValid()) // 如果指针有效
		{
			// 获取表面类型指针
			TEnumAsByte<EPhysicalSurface> PhysicalSurfaceType = PhysicalSurfaceTypePtr->SurfaceType; // 物理表面类型

			// 如果设置有效
			if (const ULyraContextEffectsSettings* LyraContextEffectsSettings = GetDefault<ULyraContextEffectsSettings>()) // 获取上下文效果设置
			{
				// 将表面类型转换为已知
				if (const FGameplayTag* SurfaceContextPtr = LyraContextEffectsSettings->SurfaceTypeToContextMap.Find(PhysicalSurfaceType)) // 查找表面上下文
				{
					FGameplayTag SurfaceContext = *SurfaceContextPtr; // 表面上下文

					TotalContexts.AddTag(SurfaceContext); // 添加上下文标签
				}
			}
		}
	}

	// 遍历活动音频组件并缓存
	for (UAudioComponent* ActiveAudioComponent : ActiveAudioComponents) // 遍历活动音频组件
	{
		if (ActiveAudioComponent) // 检查音频组件是否有效
		{
			AudioComponentsToAdd.Add(ActiveAudioComponent); // 添加到要添加的音频组件
		}
	}

	// 遍历活动Niagara组件并缓存
	for (UNiagaraComponent* ActiveNiagaraComponent : ActiveNiagaraComponents) // 遍历活动Niagara组件
	{
		if (ActiveNiagaraComponent) // 检查Niagara组件是否有效
		{
			NiagaraComponentsToAdd.Add(ActiveNiagaraComponent); // 添加到要添加的Niagara组件
		}
	}

	// 获取世界
	if (const UWorld* World = GetWorld()) // 获取世界
	{
		// 获取子系统
		if (ULyraContextEffectsSubsystem* LyraContextEffectsSubsystem = World->GetSubsystem<ULyraContextEffectsSubsystem>()) // 获取上下文效果子系统
		{
			// 设置音频组件和Niagara
			TArray<UAudioComponent*> AudioComponents; // 音频组件数组
			TArray<UNiagaraComponent*> NiagaraComponents; // Niagara组件数组

			// 生成效果
			LyraContextEffectsSubsystem->SpawnContextEffects(GetOwner(), StaticMeshComponent, Bone, 
				LocationOffset, RotationOffset, MotionEffect, TotalContexts,
				AudioComponents, NiagaraComponents, VFXScale, AudioVolume, AudioPitch); // 生成上下文效果

			// 追加结果效果
			AudioComponentsToAdd.Append(AudioComponents); // 追加音频组件
			NiagaraComponentsToAdd.Append(NiagaraComponents); // 追加Niagara组件
		}
	}

	// 追加活动音频组件
	ActiveAudioComponents.Empty(); // 清空活动音频组件
	ActiveAudioComponents.Append(AudioComponentsToAdd); // 追加要添加的音频组件

	// 追加活动
	ActiveNiagaraComponents.Empty(); // 清空活动Niagara组件
	ActiveNiagaraComponents.Append(NiagaraComponentsToAdd); // 追加要添加的Niagara组件

}

/**
 * 更新效果上下文
 */
void ULyraContextEffectComponent::UpdateEffectContexts(FGameplayTagContainer NewEffectContexts)
{
	// 重置并更新
	CurrentContexts.Reset(NewEffectContexts.Num()); // 重置当前上下文
	CurrentContexts.AppendTags(NewEffectContexts); // 追加新效果上下文
}

/**
 * 更新库
 */
void ULyraContextEffectComponent::UpdateLibraries(
	TSet<TSoftObjectPtr<ULyraContextEffectsLibrary>> NewContextEffectsLibraries)
{
	// 清除现有效果
	CurrentContextEffectsLibraries = NewContextEffectsLibraries; // 设置当前上下文效果库

	// 获取世界
	if (const UWorld* World = GetWorld()) // 获取世界
	{
		// 获取子系统
		if (ULyraContextEffectsSubsystem* LyraContextEffectsSubsystem = World->GetSubsystem<ULyraContextEffectsSubsystem>()) // 获取上下文效果子系统
		{
			// 加载并添加库到子系统                  
			LyraContextEffectsSubsystem->LoadAndAddContextEffectsLibraries(GetOwner(), CurrentContextEffectsLibraries); // 加载并添加上下文效果库
		}
	}
}